package com.demo.redis.controller;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@RestController
@SuppressWarnings({"rawtypes"})
public class RedissonTestController {

    //加锁的命令，我们参照spring包里的分布式锁代码，如果锁存在并且是当前客户端加的锁，那就续锁，如果锁不存在，则加锁。代码如下：
    private static final String OBTAIN_LOCK_SCRIPT =
            "local lockClientId = redis.call('GET', KEYS[1])\n" +
                    "if lockClientId == ARGV[1] then\n" +
                    " redis.call('PEXPIRE', KEYS[1], ARGV[2])\n" +
                    " return true\n" +
                    "elseif not lockClientId then\n" +
                    " redis.call('SET', KEYS[1], ARGV[1], 'PX', ARGV[2])\n" +
                    " return true\n" +
                    "end\n" +
                    "return false";

    //把锁保存在一个数据结构里，比如HashMap，定时任务定时扫描这个map，对每个锁进行续锁操作。代码如下：
//    private final Map<String, RedisLock> locks = new ConcurrentHashMap<>();

    //续锁命令
    private static final String RENEW_LOCK_SCRIPT =
            "local lockClientId = redis.call('GET', KEYS[1])\n" +
                    "if lockClientId == ARGV[1] then\n" +
                    " redis.call('PEXPIRE', KEYS[1], ARGV[2])\n" +
                    " return true\n" +
                    "end\n" +
                    "return false";


    //如果锁是当前客户端加的，那就续锁，否则失败。
    //写一个定时任务，定时执行续锁代码：
//    redisTemplate.execute(renewLockScript, Collections.singletonList(lockKey), clientId, String.valueOf(expireAfter));


    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RedissonClient redisson;

    @RequestMapping("/testRedisson")
    public String testRedisson() {
        RLock lock = redisson.getLock("lock");
        lock.lock(30, TimeUnit.SECONDS);
        try {
            TimeUnit.SECONDS.sleep(3);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return "Redisson";
    }
}
